﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Web;
using System.Web.Mvc;
using Mindfor.Web.Config;
using Mindfor.Web.Data;
using Mindfor.Web.Features;
using Mindfor.Web.Models;
using Mindfor.Web.Modules.Users;
using Mindfor.Web.Routing;
using NHibernate;
using NHibernate.Linq;

namespace Mindfor.Web.Modules.FeedBack.Controllers
{
	public class FeedBackController : CmsController
	{
		/// <summary>
		/// Returns PageResult which renders FeedBack index view.
		/// </summary>
		/// <param name="page">Page number.</param>
		/// <returns>PageResult.</returns>
		[UrlRoute(1, "")]
		[UrlRouteDefault(1, "page", 1)]
		[UrlRoute(2, "Page{page}")]
		[UrlRouteConstraint(2, "page", Constraints.IsInt)]
		public ActionResult Index(int page)
		{
			// get feedback items
			int pageIndex = page - 1;
			if (pageIndex < 0)
				return HttpNotFound();
			int pageSize = Module.Options[FeedBackModule.IndexPageSizeOption].GetValue<int>();
			
			IQueryable<FeedBackItem> fbQuery = Data.Query<FeedBackItem>()
				.OrderByDescending(r => r.Date);

			ViewData.Model = fbQuery.ToList().Where(r => !String.IsNullOrEmpty(r.Answer)).Skip(pageIndex * pageSize).Take(pageSize).ToList();
			ViewData["Pager"] = new PagerModel(fbQuery.Count(), pageSize);
			ViewData["IsEditable"] = User != null && User.IsInRole(CmsRoles.Administrator, FeedBackModule.FeedBackRole);

			return View();
		}


		/// <summary>
		/// Returns PageResult which renders FeedBack Admin index view.
		/// </summary>
		/// <param name="page">Page number.</param>
		/// <returns>PageResult.</returns>
		[UrlRoute(1, "", Path="Admin/Feedback")]
		[UrlRouteDefault(1, "page", 1)]
		[UrlRoute(2, "Page{page}", Path="Admin/Feedback")]
		[UrlRouteConstraint(2, "page", Constraints.IsInt)]
		[AdminLink("Отзывы", "Сайт")]
		[CmsAuthorize(FeedBackModule.FeedBackRole)]
		public ActionResult IndexAdmin(int page)
		{
			// get feedback items
			int pageSize = 20;
			int pageIndex = page - 1;
			if (pageIndex < 0)
				return HttpNotFound();

			IQueryable<FeedBackItem> fbQuery = Data.Query<FeedBackItem>().OrderByDescending(r => r.Date);
			
			ViewData.Model = fbQuery.Skip(pageIndex * pageSize).Take(pageSize).ToList();
			ViewData["EmailEnabled"] = Module.Options[FeedBackModule.EmailEnabledOption].GetValue<bool>();
			ViewData["PhoneEnabled"] = Module.Options[FeedBackModule.PhoneEnabledOption].GetValue<bool>();
			ViewData["Pager"] = new PagerModel(fbQuery.Count(), pageSize);

			return View();
		}

		/// <summary>
		/// FeedBack item creating page.
		/// </summary>
		[HttpGet]
		[UrlRoute("Add", Path="Admin/Feedback")]
		[LoadModelState]
		[ReturnUrlEnable]
		public ActionResult Add()
		{
			ViewData["EmailEnabled"] = Module.Options[FeedBackModule.EmailEnabledOption].GetValue<bool>();
			ViewData["PhoneEnabled"] = Module.Options[FeedBackModule.PhoneEnabledOption].GetValue<bool>();
			return View();
		}

		/// <summary>
		/// FeedBack item creating 'POST'-method.
		/// </summary>
		[HttpPost]
		[ValidateInput(false)]
		public ActionResult Add(FeedBackItem model)
		{
			if (ModelState.IsValid)
			{
				// save to db
				model.Date = DateTime.UtcNow;
				model.Text = Typograf.ProcessText(model.Text, TypografEntityTypes.HtmlEntities);

				// save new item to db
				using (ITransaction t = Data.BeginTransaction())
				{
					Data.SaveOrUpdate(model);
					t.Commit();
				}

				//send email to FeedBackManagers
				MailTemplate template = Data.Query<MailTemplate>().Get(FeedBackModule.MailTemplateNewFeedback, Module.Name, Language);
				if (template != null)
				{
					string relativeUrl = Url.Action("Edit", new { id = model.Id });
					Uri requestUrl = new Uri(SiteUrl, relativeUrl);

					List<MailQueue> mailList = new List<MailQueue>();

					foreach (var usr in Data.Query<User>().ToList().Where(u => u.IsInRole(FeedBackModule.FeedBackRole)))
					{
						mailList.Add(template.GenerateMailQueue(usr.Email, usr.Login, new
						{
							login = usr.Login,
							url = requestUrl,
							date = DateTime.UtcNow.ToLocalTime().ToLongTimeString()
						}));
					}

					using (ITransaction t = Data.BeginTransaction())
					{
						Data.SaveMulti(mailList);
						t.Commit();
					}
				}
				else
				{
					LogError(new InvalidOperationException(String.Format("Cannot find mail template \"{0}\" to send notifications about new feedbacks.", FeedBackModule.MailTemplateNewFeedback)));
					return Message("Ошибка при отправке e-mail сообщения. Сообщите администратору сайта об отсутствии шаблона письма для модуля обратной связи.");
				}

				// redirect
				return Message("Ваше обращение принято. Уведомление о нем отправлено администратору сайта.");
			}
			
			// redirect
			this.SaveModelState();
			return RedirectToAction("Add");
		}

		/// <summary>
		/// FeedBack item editing page.
		/// </summary>
		[HttpGet]
		[UrlSubAction("IndexAdmin")]
		[UrlRoute("{id}/Edit", Path="Admin/Feedback")]
		[UrlRouteConstraint("id", Constraints.IsInt)]
		[CmsAuthorize(FeedBackModule.FeedBackRole)]
		[LoadModelState]
		[ReturnUrlEnable]
		public ActionResult Edit(int? id)
		{
			// check if we have item
			if (id.HasValue)
			{
				FeedBackItem item = Data.Get<FeedBackItem>(id.Value);
				if (item == null)
					return HttpNotFound();

				ViewData["EmailEnabled"] = Module.Options[FeedBackModule.EmailEnabledOption].GetValue<bool>();
				ViewData["PhoneEnabled"] = Module.Options[FeedBackModule.PhoneEnabledOption].GetValue<bool>();
				ViewData.Model = item;
				return View("Edit");
			}
			return HttpNotFound();
		}

		/// <summary>
		/// FeedBack item editing 'POST'-method.
		/// </summary>
		[HttpPost]
		[CmsAuthorize(FeedBackModule.FeedBackRole)]
		[ValidateInput(false)]
		public ActionResult Edit(int id, bool? post)
		{
			// is model is valid
			FeedBackItem item = Data.Get<FeedBackItem>(id);
			if (item == null)
				return HttpNotFound();

			TryUpdateModel(item);
			if (ModelState.IsValid)
			{
				// typograf texts
				item.Text = Typograf.ProcessText(item.Text, TypografEntityTypes.HtmlEntities);
				if (String.IsNullOrWhiteSpace(item.Answer))
				{
					item.Answer = null;
				}
				else
				{
					item.Answer = Typograf.ProcessText(item.Answer, TypografEntityTypes.HtmlEntities);
				}

				// submit changes
				using (ITransaction t = Data.BeginTransaction())
				{
					Data.Update(item);
					t.Commit();
				}
				return RedirectToAction("Index");
			}
			this.SaveModelState();
			
			FeedBackItem checkItem = Data.Get<FeedBackItem>(id);
			return RedirectToAction(checkItem == null ? "Add" : "Edit");
		}

		/// <summary>
		/// Delete feedback item.
		/// </summary>
		/// <param name="id">FeedBack item id.</param>
		[HttpGet]
		[UrlSubAction("IndexAdmin")]
		[UrlRoute("{id}/Delete", Path="Admin/Feedback")]
		[UrlRouteConstraint("id", Constraints.IsInt)]
		[CmsAuthorize(FeedBackModule.FeedBackRole)]
		[ReturnUrlEnable]
		public ActionResult Delete(int id)
		{
			// get feedback item
			FeedBackItem fbItem = Data.Get<FeedBackItem>(id);
			if (fbItem == null)
				return HttpNotFound();

			// delete
			using (ITransaction t = Data.BeginTransaction())
			{
				Data.Delete(fbItem);
				t.Commit();
			}

			// return
			return RedirectToAction("IndexAdmin");
		}
	}
}